package com.dpac.core.dao.impl;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.ArrayUtils;
import org.mybatis.spring.SqlSessionTemplate;

import com.alibaba.druid.util.StringUtils;
import com.dpac.core.bean.CommonBean;
import com.dpac.core.dao.IDao;
import com.dpac.core.vo.BaseVo;
import com.dpac.core.vo.ResultVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

public class DaoImpl<T> implements IDao<T> {

	private static final int UPDATE_INTEGER_NULL_VALUE = Integer.MIN_VALUE;
	private static final long UPDATE_LONG_NULL_VALUE = Long.MIN_VALUE;
	private static final double UPDATE_DOUBLE_NULL_VALUE = Double.MIN_VALUE;
	private static final float UPDATE_FLOAT_NULL_VALUE = Float.MIN_VALUE;
	private static final String UPDATE_STRING_NULL_VALUE = "string_null_value";
	protected Class<T> entityClass; // 实体类对象
	private String entityName;// 实体名称

	public DaoImpl(Class<T> entityClass) {
		this.entityClass = entityClass;
		this.entityName = CommonBean.getTableName(entityClass);
	}

	@Resource
	private SqlSessionTemplate sqlSessionTemplate;

	/**
	 * 获取1条数据
	 * @param tPo
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public T getOne(T tPo) {
		T objResult = null;
		ResultVo rvoResult = executeQuery(tPo, "1", entityClass.getSimpleName() + "Dao.getList");
		List<?> lstResult = rvoResult.getLstResult();
		if (lstResult != null && lstResult.size() > 0) {
			objResult = (T) lstResult.get(0);
			lstResult.clear();
		}
		return objResult;
	}

	/**
	 * 获取数据列表
	 * @param tPo 持久对象
	 * @return
	 */
	public ResultVo getList(T tPo) {
		return executeQuery(tPo, "2", entityClass.getSimpleName() + "Dao.getList");
	}

	/**
	 * 执行查询
	 * @param tPo 持久对象
	 * @param sType 1-获取1条,2-获取列表
	 * @param sSelectId
	 * @return
	 */
	public ResultVo executeQuery(T tPo, String sType, String sSelectId) {
		ResultVo rvoResult = new ResultVo();
		String sHql = "select * from " + entityName;
		String sCount = "select count(*) from " + entityName;
		Field[] fields = entityClass.getDeclaredFields();
		Object[] objValue = null;
		String[] arrNonCondition = new String[] { "condition", "orderBy", "pageNum", "limitNum" };
		String sTempCondition = "";
		for (int i = 0; i < fields.length; i++) {
			String sFieldName = fields[i].getName();
			objValue = CommonBean.getFieldValue(tPo, entityClass, sFieldName);
			if (!Arrays.asList(arrNonCondition).contains(sFieldName)) {
				if ("isDelete".equals(sFieldName)) {
					String sTemp = CommonBean.clearNull((String) objValue[0], "0");
					objValue[0] = "-1".equals(sTemp) ? null : "0";
				}
				if (objValue[0] == null || "".equals(objValue[0]) || objValue[0].toString().equals("[]")) continue;
				String sSymbol = "=";
				if (objValue[0] instanceof String && (((String) objValue[0]).startsWith("%") || ((String) objValue[0]).endsWith("%"))) sSymbol = "like";
				if (!CommonBean.checkIllegalData(CommonBean.objectToString(objValue[0]))) { return rvoResult; }
				sFieldName = CommonBean.getFieldName(tPo, entityClass, fields[i].getName());
				sTempCondition += " and " + sFieldName + " " + sSymbol + " '" + objValue[0] + "'";
			}
			if ("condition".equals(sFieldName)) {
				sTempCondition += (String) objValue[0];// 直接拼接条件
			}
		}
		String sOrderBy = " order by id desc ";
		Object[] arrOrderBy = CommonBean.getFieldValue(tPo, entityClass, "orderBy");
		if ((int) arrOrderBy[1] != -1 && !StringUtils.isEmpty((String) arrOrderBy[0])) sOrderBy = (String) arrOrderBy[0];
		int iPageNum = (int) CommonBean.getFieldValue(tPo, entityClass, "pageNum")[0];
		int iLimitNum = (int) CommonBean.getFieldValue(tPo, entityClass, "limitNum")[0];
		sHql = sHql + " where 1=1 " + sTempCondition + sOrderBy;
		sCount = sCount + " where 1=1 " + sTempCondition;
		if (iPageNum <= 0) {
			iPageNum = 1;
		}
		if (iLimitNum <= 0) {
			iLimitNum = 20;
		}
		if ("1".equals(sType)) {
			iPageNum = 1;
			iLimitNum = 1;
		} else {
			long totalNum = sqlSessionTemplate.selectOne("selectCount", sCount);
			int iLastPageNum = (int) (totalNum % iLimitNum == 0 ? totalNum / iLimitNum : totalNum / iLimitNum + 1);
			if (Integer.MAX_VALUE == iPageNum || iPageNum > iLastPageNum) {
				iPageNum = iLastPageNum;
			}
		}
		PageHelper.startPage(iPageNum, iLimitNum);
		PageInfo<?> pageInfo = null;
		List<T> lstResult = sqlSessionTemplate.selectList(sSelectId, sHql);
		pageInfo = new PageInfo<T>(lstResult);
		rvoResult.setSuccess(true);
		rvoResult.setLstResult(lstResult);
		rvoResult.setTotalPage(pageInfo.getPages());
		rvoResult.setTotalSize(CommonBean.stringToInteger(CommonBean.longToString(pageInfo.getTotal())));
		return rvoResult;
	}

	@Override
	public ResultVo save(T tPo) {
		ResultVo rvoResult = new ResultVo();
		try {
			// 设置公共默认值
			Object[] objCreateTime = CommonBean.getFieldValue(tPo, entityClass, "createTime");
			if ((int) objCreateTime[1] != -1 && StringUtils.isEmpty((String) objCreateTime[0])) {
				Field field = entityClass.getDeclaredField("createTime");
				field.setAccessible(true);
				field.set(tPo, CommonBean.getNowTime());// 默认为当前时间
			}
			Object[] objIsDelete = CommonBean.getFieldValue(tPo, entityClass, "isDelete");
			if ((int) objIsDelete[1] != -1 && StringUtils.isEmpty((String) objIsDelete[0])) {
				Field field = entityClass.getDeclaredField("isDelete");
				field.setAccessible(true);
				field.set(tPo, "0");// 默认为0
			}
			// 保存操作
			Field[] fields = entityClass.getDeclaredFields();
			Object[] objValue;
			String sInsertSql = "insert into " + entityName + " (";
			String sPrams = "";
			String sValues = "";
			int index = 0;
			for (int i = 0; i < fields.length; i++) {
				String sFieldName = CommonBean.getFieldName(tPo, entityClass, fields[i].getName());
				objValue = CommonBean.getFieldValue(tPo, entityClass, fields[i].getName());
				if (objValue[0] == null || "".equals(objValue[0]) || objValue[0].toString().equals("[]")) {
					continue;
				} else {
					if (!CommonBean.checkIllegalData(CommonBean.objectToString(objValue[0]))) { return rvoResult; }
					if (index > 0) {
						sPrams += ", ";
						sValues += ", ";
					}
					sPrams += sFieldName;
					if (objValue[0] instanceof byte[]) {
						sValues += "'" + new String((byte[]) objValue[0]) + "'";
					} else if (objValue[0] instanceof Boolean) {
						sValues += "'" + ((boolean) objValue[0] == true ? 1 : 0) + "'";
					} else {
						sValues += "'" + objValue[0] + "'";
					}
					index++;
				}
			}
			sInsertSql += sPrams + ") value (" + sValues + ")";
			BaseVo baseVo = new BaseVo();
			baseVo.setMybatisSql(sInsertSql);
			sqlSessionTemplate.insert("save", baseVo);
			// 设置返回信息
			rvoResult.setId(baseVo.getMybatisId());
			rvoResult.setSuccess(true);
			rvoResult.setMessage("保存数据成功！");
		} catch (Exception e) {
			rvoResult.setSuccess(false);
			rvoResult.setMessage("保存数据失败！");
			e.printStackTrace();
		}
		return rvoResult;
	}

	@Override
	public ResultVo update(T tPo, Object[] arrNecessaryCondition) {
		ResultVo rvoResult = new ResultVo();
		int iExecuteCount = -1, iConditionCount = 0;
		try {
			System.out.println(CommonBean.getNowTime() + "开始更新...");
			if (arrNecessaryCondition == null) arrNecessaryCondition = new String[] { "id", "condition" };
			Field[] entityFields = entityClass.getDeclaredFields();
			Field condition = BaseVo.class.getDeclaredField("condition");
			Field fieldValue = BaseVo.class.getDeclaredField("fieldValue");
			Field[] fields = ArrayUtils.addAll(entityFields, condition, fieldValue);
			Object[] objValue;
			String sFullHql = "update " + entityName + " set ";
			String sTempCondition = "";
			ArrayList<Object> arrParameters = new ArrayList<Object>();
			for (int i = 0; i < fields.length; i++) {
				String sFieldName = CommonBean.getFieldName(tPo, entityClass, fields[i].getName());
				objValue = CommonBean.getFieldValue(tPo, entityClass, fields[i].getName());
				boolean bIsNecessary = Arrays.asList(arrNecessaryCondition).contains(sFieldName);
				if (bIsNecessary) {// 必要条件
					if (objValue[0] == null || "".equals(objValue[0]) || objValue[0].toString().equals("[]")) continue;
					if (!CommonBean.checkIllegalData(CommonBean.objectToString(objValue[0]))) { return rvoResult; }
					if ("condition".equals(sFieldName)) {
						sTempCondition += (String) objValue[0];// 直接拼接条件
					} else {// 非必要条件
						String sAndValue = setValue(sFieldName, objValue[0]);
						sTempCondition += " and " + sAndValue.substring(0, sAndValue.length() - 1);
					}
					iConditionCount++;
				} else {// 要更新的字段
					if (!CommonBean.checkIllegalData(CommonBean.objectToString(objValue[0]))) { return rvoResult; }
					if ("modify_time".equals(sFieldName) && StringUtils.isEmpty((String) objValue[0])) {
						objValue[0] = CommonBean.getNowTime();// 为空时给默认时间
					}
					if (objValue[0] == null || "".equals(objValue[0]) || objValue[0].toString().equals("[]")) continue;
					if ("field_value".equals(sFieldName)) {
						sFullHql += (String) objValue[0] + " ,";// 直接拼接
					} else {
						sFullHql += setValue(sFieldName, objValue[0]);
					}
				}
				if (!"field_value".equals(sFieldName) && !"condition".equals(sFieldName)) arrParameters.add(objValue[0]);
			}
			sFullHql = sFullHql.substring(0, sFullHql.length() - 1) + " where 1=1 " + sTempCondition;
			// 防止没有条件的情况下更新数据
			if (iConditionCount < 1 || sFullHql.toLowerCase().indexOf("and ") < 0) {
				rvoResult.setSuccess(false);
				rvoResult.setMessage("更新数据失败，请传入必要值！");
				return rvoResult;
			}
			// 执行更新
			iExecuteCount = sqlSessionTemplate.update("update", sFullHql);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (iExecuteCount >= 0) {
			rvoResult.setSuccess(true);
			rvoResult.setMessage("更新数据成功！");
		} else {
			rvoResult.setSuccess(false);
			rvoResult.setMessage("更新数据失败！");
		}
		return rvoResult;
	}

	@Override
	public ResultVo delete(T tPo, Object[] arrNecessaryCondition) {
		ResultVo rvoResult = new ResultVo();
		int iExecuteCount = -1, iConditionCount = 0;
		try {
			System.out.println(CommonBean.getNowTime() + "开始删除...");
			if (arrNecessaryCondition == null) arrNecessaryCondition = new String[] { "id", "condition" };
			Field[] entityFields = entityClass.getDeclaredFields();
			Field condition = BaseVo.class.getDeclaredField("condition");
			Field[] fields = ArrayUtils.addAll(entityFields, condition);
			Object[] objValue;
			String sHql = "update " + entityName + " set ";
			String sTempCondition = "";
			for (int i = 0; i < fields.length; i++) {
				String sFieldName = fields[i].getName();
				objValue = CommonBean.getFieldValue(tPo, entityClass, sFieldName);
				boolean bIsNecessary = Arrays.asList(arrNecessaryCondition).contains(sFieldName);
				if (bIsNecessary) {// 必要条件
					if (objValue[0] == null || "".equals(objValue[0])) continue;
					if (!CommonBean.checkIllegalData(CommonBean.objectToString(objValue[0]))) { return rvoResult; }
					if ("condition".equals(sFieldName)) {
						sTempCondition += (String) objValue[0];// 直接拼接条件
					} else {// 更新条件
						sFieldName = CommonBean.getFieldName(tPo, entityClass, sFieldName);
						String sAndValue = setValue(sFieldName, objValue[0]);
						sTempCondition += " and " + sAndValue.substring(0, sAndValue.length() - 1);
					}
					iConditionCount++;
				} else {// 要更新的字段
					if (!CommonBean.checkIllegalData(CommonBean.objectToString(objValue[0]))) { return rvoResult; }
					if ("isDelete".equals(sFieldName)) {
						objValue[0] = "1";// 强制将is_delete设置为1of
						sTempCondition += " and is_delete = '0'";
					} else if ("deleteTime".equals(sFieldName) && StringUtils.isEmpty((String) objValue[0])) {
						objValue[0] = CommonBean.getNowTime();// 为空时给默认时间
					} else if (!"deleteNumber".equals(sFieldName)) {
						continue;// 其它字段不更新
					}
					if (objValue[0] == null || "".equals(objValue[0])) continue;
					sFieldName = CommonBean.getFieldName(tPo, entityClass, sFieldName);
					sHql += setValue(sFieldName, objValue[0]);
				}
			}
			sHql = sHql.substring(0, sHql.length() - 1) + " where 1=1 " + sTempCondition;
			// 防止没有条件的情况下删除数据
			if (iConditionCount < 1 || sHql.toLowerCase().indexOf("and ") < 0) {
				rvoResult.setSuccess(false);
				rvoResult.setMessage("删除数据失败，请传入必要值！");
				return rvoResult;
			}
			// 执行更新
			iExecuteCount = sqlSessionTemplate.update("update", sHql);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (iExecuteCount >= 0) {
			rvoResult.setSuccess(true);
			rvoResult.setMessage("删除数据成功！");
		} else {
			rvoResult.setSuccess(false);
			rvoResult.setMessage("删除数据失败！");
		}
		return rvoResult;
	}

	private String setValue(String sFieldName, Object objValue) {
		String sResult = "";
		if (objValue instanceof String) {
			if (UPDATE_STRING_NULL_VALUE.equals(objValue)) {
				sResult = sFieldName + " = null ,";
			} else {
				sResult = sFieldName + " = '" + objValue + "' ,";
			}
		} else if (objValue instanceof Date) {
			sResult = sFieldName + " = '" + objValue + "' ,";
		} else if (objValue instanceof Integer) {
			if (UPDATE_INTEGER_NULL_VALUE == (Integer) objValue) {
				sResult = sFieldName + " = null ,";
			} else {
				sResult = sFieldName + " = '" + objValue + "' ,";
			}
		} else if (objValue instanceof Double) {
			if (UPDATE_DOUBLE_NULL_VALUE == (Double) objValue) {
				sResult = sFieldName + " = null ,";
			} else {
				sResult = sFieldName + " = '" + objValue + "' ,";
			}
		} else if (objValue instanceof Float) {
			if (UPDATE_FLOAT_NULL_VALUE == (Float) objValue) {
				sResult = sFieldName + " = null ,";
			} else {
				sResult = sFieldName + " = '" + objValue + "' ,";
			}
		} else if (objValue instanceof Long) {
			if (UPDATE_LONG_NULL_VALUE == (Long) objValue) {
				sResult = sFieldName + " = null ,";
			} else {
				sResult = sFieldName + " = '" + objValue + "' ,";
			}
		} else {
			if (UPDATE_STRING_NULL_VALUE.equals(objValue.toString())) {
				sResult = sFieldName + " = null ,";
			} else {
				sResult = sFieldName + " = '" + objValue + "' ,";
			}
		}
		return sResult;
	}

}
